package com.gongxt;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.IBinder;
import android.provider.CallLog;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;

import com.gongxt.data.CallAndSmsHelper;
import com.gongxt.data.ContactHelper;
import com.gongxt.data.ContactInfo;
import com.gongxt.data.SMS;
import com.gongxt.observer.CallAndSmsObserver;

public class UpdateService extends Service {
	private static String TAG = "UpdateService";
	
	// type define for dial tab
	public static int SHOW_DIAL_DEFAULT = 0;
	public static int SHOW_DIAL_NORMAL = 1;
	public static int SHOW_DIAL_FAVOR = 2;
	private int mDailTabType = SHOW_DIAL_DEFAULT;

	// type define for sms tab
	public static int SHOW_SMS_DEFAULT = 0;
	public static int SHOW_SMS_NORMAL = 1;
	public static int SHOW_SMS_FAVOR = 2;
	private int mSmsTabType = SHOW_SMS_DEFAULT;
	
	// action extra data name
	public static String EXT_FAVOR_NUMBER = "favor_number";
	
	// update timer
	//Timer mUpdateTimer = null;
	
	// return normal timer
	private static int RET_INTERVAL = 5000;			// after 5 seconds, return normal
	private Timer mTimerReturn = null;
	private ReturnNormalTask mTaskReturn = new ReturnNormalTask();
	
	// favor members
	private ArrayList<Long> mFavorMember = null;
	private ArrayList<ContactInfo> mArrDialFavor = new ArrayList<ContactInfo>();
	private ArrayList<ContactInfo> mArrSmsFavor = new ArrayList<ContactInfo>();
	
	private static int FULL_SIZE = 3;
	private int mDialCurrPosFULL = 0;
	private int mSmsCurrPosFULL = 0;
	
	private BroadcastReceiver screenOnReceiver = null;
	private BroadcastReceiver timeReceiver = null;
	
	private CallAndSmsObserver mCallObserver = null;
	private CallAndSmsObserver mSMSObserver = null;
	
	@Override
	public void onStart(Intent intent, int startId) {
		Log.d(TAG, "onStart called");
		
		if (intent != null && intent.getAction() != null){
			Log.i(TAG, "intent action: " + intent.getAction().toString());
			
			if (getString(R.string.act_show_dial_favor).equals(intent.getAction().toString())){
				prepareDialFavorContact();
				
			}else if (getString(R.string.act_show_dial_normal).equals(intent.getAction().toString())){
				mDailTabType = SHOW_DIAL_NORMAL;
				
			}else if (getString(R.string.act_show_sms_favor).equals(intent.getAction().toString())){
				prepareSmsFavorContact();
				
			}else if (getString(R.string.act_show_sms_normal).equals(intent.getAction().toString())){
				mSmsTabType = SHOW_SMS_NORMAL;
			}
		}
						
		// when received screen on broadcast, start service
		if (screenOnReceiver == null){
			screenOnReceiver = new BroadcastReceiver() {
				  @Override
				  public void onReceive(Context context, Intent intent) {
					  startService(new Intent(context, UpdateService.class));
				  }
				};
				
			this.registerReceiver(screenOnReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
		}
		 
		// when received time tick, update view
		if (timeReceiver == null){
			timeReceiver = new BroadcastReceiver() {
				  @Override
				  public void onReceive(Context context, Intent intent) {
					  // only when dial tab is showing time, we need time tick to update
					  if (mDailTabType != SHOW_DIAL_FAVOR){
						  makeViewUpdate();
					  }
				  }
				};
				
			this.registerReceiver(timeReceiver, new IntentFilter(Intent.ACTION_TIME_TICK));
		}
		
		// regist observer for miss call and received sms
		if (mCallObserver == null){
			mCallObserver = new CallAndSmsObserver(getApplicationContext(), new Handler());
			this.getContentResolver().registerContentObserver(CallLog.Calls.CONTENT_URI, false, mCallObserver);
		}
		
		if (mSMSObserver == null){
			mSMSObserver = new CallAndSmsObserver(getApplicationContext(), new Handler());
			this.getContentResolver().registerContentObserver(SMS.CONTENT_URI, true, mSMSObserver);
		}
		
		// update views
		makeViewUpdate();
		
	}

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}
	
	private void prepareDialFavorContact(){
		// get favor member
		mFavorMember = ContactHelper.getInstance(getApplicationContext()).getStarredMembers();
		if (mFavorMember.size() > 0){
							
			// only when last motion is show favor or is the first motion, we need to get new favor contact
			if (mDailTabType == SHOW_DIAL_FAVOR || mDailTabType == SHOW_DIAL_DEFAULT){
				mArrDialFavor.clear();
										
				// if is last three, begin from first
				if (((mDialCurrPosFULL * FULL_SIZE) - mFavorMember.size()) >= 0){
					mDialCurrPosFULL = 0;
				}
				
				// three favor contact
				for (int i=0; i<FULL_SIZE; i++){
					if (mFavorMember.size() > (mDialCurrPosFULL * FULL_SIZE + i)){
						Long lContactID = mFavorMember.get(mDialCurrPosFULL * FULL_SIZE + i);
						mArrDialFavor.add(ContactHelper.getInstance(getApplicationContext()).getContact(lContactID));
					}
				}

				// move to next three person
				mDialCurrPosFULL++;
				Log.d(TAG, "mDialCurrPosFULL++");
			}
			
			// set current dial pad type
			mDailTabType = SHOW_DIAL_FAVOR;
			
		}else{
			// if no favor member found, nothing happens
			mDailTabType = SHOW_DIAL_NORMAL;
		}
	}
	
	private void prepareSmsFavorContact(){
		// get favor member
		mFavorMember = ContactHelper.getInstance(getApplicationContext()).getStarredMembers();
		if (mFavorMember.size() > 0){
							
			// only when last motion is show favor or is the first motion, we need to get new favor contact
			if (mSmsTabType == SHOW_SMS_FAVOR || mSmsTabType == SHOW_SMS_DEFAULT){
				mArrSmsFavor.clear();
										
				// if is last three, begin from first
				if (((mSmsCurrPosFULL * FULL_SIZE) - mFavorMember.size()) >= 0){
					mSmsCurrPosFULL = 0;
				}
				
				// three favor contact
				for (int i=0; i<FULL_SIZE; i++){
					if (mFavorMember.size() > (mSmsCurrPosFULL * FULL_SIZE + i)){
						Long lContactID = mFavorMember.get(mSmsCurrPosFULL * FULL_SIZE + i);
						mArrSmsFavor.add(ContactHelper.getInstance(getApplicationContext()).getContact(lContactID));
					}
				}

				// move to next three person
				mSmsCurrPosFULL++;
			}
			
			// set current sms pad type
			mSmsTabType = SHOW_SMS_FAVOR;
			
		}else{
			// if no favor member found, nothing happens
			mSmsTabType = SHOW_SMS_NORMAL;
		}		
	}
	
	private void makeViewUpdate(){
		RemoteViews updateViews = new RemoteViews(this.getPackageName(), R.layout.contact_person);
				
		// set return normal timer
		if ((mDailTabType == SHOW_DIAL_FAVOR) || (mSmsTabType == SHOW_SMS_FAVOR)){
			// set return normal timer
			if (mTimerReturn != null){
				mTimerReturn.cancel();
			}

			if (mTaskReturn != null){
				mTaskReturn.cancel();
			}
			
			mTimerReturn = new Timer();
			mTaskReturn = new ReturnNormalTask();
			mTimerReturn.schedule(mTaskReturn, RET_INTERVAL);
			
		}else{
			// cancel return timer
			if (mTimerReturn != null){
				mTimerReturn.cancel();
			}
			
			if (mTaskReturn != null){
				mTaskReturn.cancel();
			}
			
		}
		
		// dial tab
		setViewForDialTab(updateViews);
		
		// sms tab
		setViewForSmsTab(updateViews);
		
		// update widget
		ComponentName thisWidget = new ComponentName(this, ContactPersonProvider.class);
		AppWidgetManager mng = AppWidgetManager.getInstance(this);
		mng.updateAppWidget(thisWidget, updateViews);
	}

	
	private void setViewForDialTab(RemoteViews updateViews){		
		Log.d(TAG, "setViewForDialTab called");
		
		if (mDailTabType == SHOW_DIAL_NORMAL || mDailTabType == SHOW_DIAL_DEFAULT){
			updateViews.setViewVisibility(R.id.layout_dial, View.VISIBLE);
			updateViews.setViewVisibility(R.id.layout_dial_favor, View.GONE);
			
			// update date Text every 1 min.
//			Calendar c = Calendar.getInstance();
//			int delayMillsec = (59 - c.get(Calendar.SECOND))*1000 + (1000 - c.get(Calendar.MILLISECOND));
//			if (mUpdateTimer != null){
//				mUpdateTimer.cancel();
//			}
//			mUpdateTimer = new Timer();
//			mUpdateTimer.schedule(new DateTimeTask(), delayMillsec , 60000);
			
			int nMissCall = CallAndSmsHelper.getInstance(getApplicationContext()).checkMissCallNumber();
			
			// set dial button
			Intent iDial= new Intent(getString(R.string.act_to_system_dial));
			PendingIntent piDial = PendingIntent.getBroadcast(this.getApplicationContext(), 0, iDial, 0);
			//updateViews.setOnClickPendingIntent(R.id.btn_dial, piDial);
			updateViews.setOnClickPendingIntent(R.id.layout_tab_dial, piDial);

			if (nMissCall == 0){
				updateViews.setViewVisibility(R.id.layout_miss_call, View.GONE);

			}else{
				updateViews.setViewVisibility(R.id.layout_miss_call, View.VISIBLE);				
				
				// set miss call button
				Intent iMissCall = new Intent(getString(R.string.act_to_system_miss_call));
				PendingIntent piMissCall = PendingIntent.getBroadcast(this.getApplicationContext(), 0, iMissCall, 0);
				updateViews.setOnClickPendingIntent(R.id.layout_miss_call, piMissCall);
				
				// set miss call number
				updateViews.setTextViewText(R.id.txt_miss_call_number, String.valueOf(nMissCall));
			}
			
			// set time and date
			updateViews.setTextViewText(R.id.txt_time_time, getCurrTime());
			updateViews.setTextViewText(R.id.txt_time_date, getCurrDate());
			updateViews.setTextViewText(R.id.txt_time_day, getCurrDayOfWeek());
			
		}else if (mDailTabType == SHOW_DIAL_FAVOR){
			updateViews.setViewVisibility(R.id.layout_dial, View.GONE);
			updateViews.setViewVisibility(R.id.layout_dial_favor, View.VISIBLE);
			
			ContactInfo cInfo = null;
			Intent intentCall = null;
			PendingIntent pIntentCall = null;
			
			// set first favor image 
			if (mArrDialFavor.size() >= 1){
				cInfo = mArrDialFavor.get(0);
				Log.d(TAG, cInfo.getPhoneCid() + " " + cInfo.getPrimayPhone());
				
				intentCall = new Intent(getString(R.string.act_dial_favor_1));
				intentCall.putExtra(EXT_FAVOR_NUMBER, cInfo.getPrimayPhone());
				pIntentCall = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intentCall, PendingIntent.FLAG_UPDATE_CURRENT);
				updateViews.setOnClickPendingIntent(R.id.btn_dial_favor_1, pIntentCall);				
				
				if (cInfo.getImage() != null){
					updateViews.setImageViewBitmap(R.id.img_dial_favor_1, BitmapFactory.decodeByteArray(cInfo.getImage(), 0, cInfo.getImage().length));
				}else{
					updateViews.setImageViewResource(R.id.img_dial_favor_1, R.drawable.ic_contact_picture);
				}
				
				updateViews.setTextViewText(R.id.txt_dial_favor_name_1, cInfo.getDisplayName());
			
			}
			
			// set second favor image
			if (mArrDialFavor.size() >= 2){
				cInfo = mArrDialFavor.get(1);
				Log.d(TAG, cInfo.getPhoneCid() + " " + cInfo.getPrimayPhone());
				updateViews.setViewVisibility(R.id.btn_dial_favor_2, View.VISIBLE);
				
				intentCall = new Intent(getString(R.string.act_dial_favor_2));
				intentCall.putExtra(EXT_FAVOR_NUMBER, cInfo.getPrimayPhone());
				pIntentCall = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intentCall, PendingIntent.FLAG_UPDATE_CURRENT);
				updateViews.setOnClickPendingIntent(R.id.btn_dial_favor_2, pIntentCall);				
				
				if (cInfo.getImage() != null){
					updateViews.setImageViewBitmap(R.id.img_dial_favor_2, BitmapFactory.decodeByteArray(cInfo.getImage(), 0, cInfo.getImage().length));
				}else{
					updateViews.setImageViewResource(R.id.img_dial_favor_2, R.drawable.ic_contact_picture);
				}
				
				updateViews.setTextViewText(R.id.txt_dial_favor_name_2, cInfo.getDisplayName());

			}else{
				updateViews.setViewVisibility(R.id.btn_dial_favor_2, View.INVISIBLE);
			}
			
			// set third favor image
			if (mArrDialFavor.size() >= 3){
				cInfo = mArrDialFavor.get(2);
				Log.d(TAG, cInfo.getPhoneCid() + " " + cInfo.getPrimayPhone());
				updateViews.setViewVisibility(R.id.btn_dial_favor_3, View.VISIBLE);

				intentCall = new Intent(getString(R.string.act_dial_favor_3));
				intentCall.putExtra(EXT_FAVOR_NUMBER, cInfo.getPrimayPhone());
				pIntentCall = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intentCall, PendingIntent.FLAG_UPDATE_CURRENT);
				updateViews.setOnClickPendingIntent(R.id.btn_dial_favor_3, pIntentCall);				
				
				if (cInfo.getImage() != null){
					updateViews.setImageViewBitmap(R.id.img_dial_favor_3, BitmapFactory.decodeByteArray(cInfo.getImage(), 0, cInfo.getImage().length));
				}else{
					updateViews.setImageViewResource(R.id.img_dial_favor_3, R.drawable.ic_contact_picture);
				}
				
				updateViews.setTextViewText(R.id.txt_dial_favor_name_3, cInfo.getDisplayName());
			}else{
				updateViews.setViewVisibility(R.id.btn_dial_favor_3, View.INVISIBLE);
				
			}
		}		
		
		// button to show dial favor person
		Intent iDialFavor = new Intent(getString(R.string.act_show_dial_favor));
		PendingIntent pIDialFavor = PendingIntent.getBroadcast(this.getApplicationContext(), 0, iDialFavor, 0);
		updateViews.setOnClickPendingIntent(R.id.btn_dial_show_favor, pIDialFavor);
		
		// button to show dial normal 
		Intent iDialNormal = new Intent(getString(R.string.act_show_dial_normal));
		PendingIntent pIDialNormal = PendingIntent.getBroadcast(this.getApplicationContext(), 0, iDialNormal, 0);
		updateViews.setOnClickPendingIntent(R.id.btn_dial_show_normal, pIDialNormal);
		
	}
	
	private void setViewForSmsTab(RemoteViews updateViews){
		Log.d(TAG, "setViewForSmsTab called");
		
		if (mSmsTabType == SHOW_SMS_NORMAL || mSmsTabType == SHOW_SMS_DEFAULT){
			updateViews.setViewVisibility(R.id.layout_sms, View.VISIBLE);
			updateViews.setViewVisibility(R.id.layout_sms_favor, View.GONE);

			// show received sms number when we have
			int nReceivedSmsNumber = CallAndSmsHelper.getInstance(getApplicationContext()).checkReceivedSmsNumber(); 
			if (nReceivedSmsNumber != 0){
				updateViews.setViewVisibility(R.id.layout_received_sms, View.VISIBLE);
				
				// set received sms button
				Intent iReceivedSms = new Intent(getString(R.string.act_to_system_received_sms));
				PendingIntent piReceivedSms = PendingIntent.getBroadcast(this.getApplicationContext(), 0, iReceivedSms, 0);
				updateViews.setOnClickPendingIntent(R.id.layout_received_sms, piReceivedSms);
			
				// set received sms number
				updateViews.setTextViewText(R.id.txt_received_sms_number, String.valueOf(nReceivedSmsNumber));
				
			}else{
				updateViews.setViewVisibility(R.id.layout_received_sms, View.GONE);
				
			}
			
			// set sms button
			Intent iSms= new Intent(getString(R.string.act_to_system_sms));
			PendingIntent piSms = PendingIntent.getBroadcast(this.getApplicationContext(), 0, iSms, 0);
			//updateViews.setOnClickPendingIntent(R.id.btn_new_sms, piSms);
			updateViews.setOnClickPendingIntent(R.id.layout_tab_sms, piSms);
			
			// set sms count
			int nSmsCount = CallAndSmsHelper.getInstance(getApplicationContext()).getInboxSmsCount();
			updateViews.setTextViewText(R.id.txt_sms_count, String.valueOf(nSmsCount));
			
		}else if (mSmsTabType == SHOW_SMS_FAVOR){
			updateViews.setViewVisibility(R.id.layout_sms, View.GONE);
			updateViews.setViewVisibility(R.id.layout_sms_favor, View.VISIBLE);

			ContactInfo cInfo = null;
			Intent intentCall = null;
			PendingIntent pIntentCall = null;
			
			// set first favor image 
			if (mArrSmsFavor.size() >= 1){
				cInfo = mArrSmsFavor.get(0);
				Log.d(TAG, cInfo.getPhoneCid() + " " + cInfo.getPrimayPhone());
				
				intentCall = new Intent(getString(R.string.act_sms_favor_1));
				intentCall.putExtra(EXT_FAVOR_NUMBER, cInfo.getPrimayPhone());
				pIntentCall = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intentCall, PendingIntent.FLAG_UPDATE_CURRENT);
				updateViews.setOnClickPendingIntent(R.id.btn_sms_favor_1, pIntentCall);				
				
				if (cInfo.getImage() != null){
					updateViews.setImageViewBitmap(R.id.img_sms_favor_1, BitmapFactory.decodeByteArray(cInfo.getImage(), 0, cInfo.getImage().length));
				}else{
					updateViews.setImageViewResource(R.id.btn_sms_favor_1, R.drawable.ic_contact_picture);
				}
				
				updateViews.setTextViewText(R.id.txt_sms_favor_name_1, cInfo.getDisplayName());
			}
			
			// set second favor image
			if (mArrSmsFavor.size() >= 2){
				cInfo = mArrSmsFavor.get(1);
				Log.d(TAG, cInfo.getPhoneCid() + " " + cInfo.getPrimayPhone());
				updateViews.setViewVisibility(R.id.btn_sms_favor_2, View.VISIBLE);
				
				intentCall = new Intent(getString(R.string.act_sms_favor_2));
				intentCall.putExtra(EXT_FAVOR_NUMBER, cInfo.getPrimayPhone());
				pIntentCall = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intentCall, PendingIntent.FLAG_UPDATE_CURRENT);
				updateViews.setOnClickPendingIntent(R.id.btn_sms_favor_2, pIntentCall);				
				
				if (cInfo.getImage() != null){
					updateViews.setImageViewBitmap(R.id.img_sms_favor_2, BitmapFactory.decodeByteArray(cInfo.getImage(), 0, cInfo.getImage().length));
				}else{
					updateViews.setImageViewResource(R.id.img_sms_favor_2, R.drawable.ic_contact_picture);
				}
				
				updateViews.setTextViewText(R.id.txt_sms_favor_name_2, cInfo.getDisplayName());
				
			}else{
				updateViews.setViewVisibility(R.id.btn_sms_favor_2, View.INVISIBLE);
			}
			
			// set third favor image
			if (mArrSmsFavor.size() >= 3){
				cInfo = mArrSmsFavor.get(2);
				Log.d(TAG, cInfo.getPhoneCid() + " " + cInfo.getPrimayPhone());
				updateViews.setViewVisibility(R.id.btn_sms_favor_3, View.VISIBLE);

				intentCall = new Intent(getString(R.string.act_sms_favor_3));
				intentCall.putExtra(EXT_FAVOR_NUMBER, cInfo.getPrimayPhone());
				pIntentCall = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intentCall, PendingIntent.FLAG_UPDATE_CURRENT);
				updateViews.setOnClickPendingIntent(R.id.btn_sms_favor_3, pIntentCall);				
				
				if (cInfo.getImage() != null){
					updateViews.setImageViewBitmap(R.id.img_sms_favor_3, BitmapFactory.decodeByteArray(cInfo.getImage(), 0, cInfo.getImage().length));
				}else{
					updateViews.setImageViewResource(R.id.img_sms_favor_3, R.drawable.ic_contact_picture);
				}
				
				updateViews.setTextViewText(R.id.txt_sms_favor_name_3, cInfo.getDisplayName());
				
			}else{
				updateViews.setViewVisibility(R.id.btn_sms_favor_3, View.INVISIBLE);
			}
			
		}		
		
		// button to show sms favor person
		Intent iSmsFavor = new Intent(getString(R.string.act_show_sms_favor));
		PendingIntent pISmsFavor = PendingIntent.getBroadcast(this.getApplicationContext(), 0, iSmsFavor, 0);
		updateViews.setOnClickPendingIntent(R.id.btn_sms_show_favor, pISmsFavor);
		
		// button to show sms normal 
		Intent iSmsNormal = new Intent(getString(R.string.act_show_sms_normal));
		PendingIntent pISmsNormal = PendingIntent.getBroadcast(this.getApplicationContext(), 0, iSmsNormal, 0);
		updateViews.setOnClickPendingIntent(R.id.btn_sms_show_normal, pISmsNormal);		
	}
	
	private String getCurrTime(){
		Calendar c = Calendar.getInstance();
		SimpleDateFormat f = new SimpleDateFormat("HH:mm");
		String strTime = null;
		strTime = f.format(c.getTime());
		
		if (strTime != null){
			return strTime;
		}else{
			return "";
		}
	}
	
	private String getCurrDate(){
		Calendar c = Calendar.getInstance();
		SimpleDateFormat f = new SimpleDateFormat("yyyy/MM/dd");
		String strTime = null;
		strTime = f.format(c.getTime());
		
		if (strTime != null){
			return strTime;
		}else{
			return "";
		}		
	}
	
	private String getCurrDayOfWeek(){
		Calendar c = Calendar.getInstance();
		String[] strDay = getResources().getStringArray(R.array.day_of_week);
		return strDay[c.get(Calendar.DAY_OF_WEEK) - 1];
	}
	
	private class ReturnNormalTask extends TimerTask{
	
		@Override
		public void run() {
			Log.d(TAG, "DateTimeTask run");
			if (mDailTabType != SHOW_DIAL_DEFAULT){
				mDailTabType = SHOW_DIAL_NORMAL;
			}
			
			if (mSmsTabType != SHOW_SMS_DEFAULT){
				mSmsTabType = SHOW_SMS_NORMAL;
			}
			
			makeViewUpdate();
		}
	}	
	
//	private class DateTimeTask extends TimerTask{
//		
//		@Override
//		public void run() {
//			Log.d(TAG, "DateTimeTask run");
//			makeViewUpdate();
//		}
//	}
}
